Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sip/transp: add win32 local transport addr fallback #1001

Merged
merged 2 commits into from
Nov 6, 2023

Conversation

sreimers
Copy link
Member

@sreimers sreimers commented Nov 5, 2023

tcp_conn_local_get function does not always return information about the host address when the socket has been bound to an unspecified address.

fixes baresip/baresip#2797

@sreimers
Copy link
Member Author

sreimers commented Nov 5, 2023

@cspiel1 on windows tcp_conn_local_get returns any address if tcp connection is not connected or accepted. So looks like connh is called to early.

https://github.com/baresip/re/blob/main/src/sip/transp.c#L795-L796

(btw. looks like connh err is ignored and overriden by secure path).

The getsockname function does not always return information about the host address when the socket has been bound to an unspecified address, unless the socket has been connected with connect or accept (for example, using ADDR_ANY). A Windows Sockets application must not assume that the address will be specified unless the socket is connected. The address that will be used for the socket is unknown unless the socket is connected when used in a multihomed host. If the socket is using a connectionless protocol, the address may not be available until I/O occurs on the socket.

https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-getsockname

@alfredh
Copy link
Contributor

alfredh commented Nov 6, 2023

/**
 * Get local network address of TCP Connection
 *
 * @param tc    TCP Connection
 * @param local Returned local network address
 *
 * @return 0 if success, otherwise errorcode
 */
int tcp_conn_local_get(const struct tcp_conn *tc, struct sa *local)
{
	int err;

	if (!tc || !local)
		return EINVAL;

	sa_init(local, AF_UNSPEC);
	err = getsockname(tc->fdc, &local->u.sa, &local->len);

	if (err < 0) {
		err = RE_ERRNO_SOCK;
		DEBUG_WARNING("conn local get: getsockname(): %m\n", err);
	}

	return err;
}

This only works if the TCP connection is "connected".

@sreimers sreimers force-pushed the win32_einval_tcp_tls_err branch from 01d3908 to 82c456c Compare November 6, 2023 08:26
@sreimers sreimers changed the title sip/request: fix win32 tcp/tls sa check sip/transp: fix win32 tcp/tls local addr fallback Nov 6, 2023
@sreimers sreimers marked this pull request as ready for review November 6, 2023 09:45
@sreimers sreimers changed the title sip/transp: fix win32 tcp/tls local addr fallback sip/transp: add win32 tcp/tls local transport addr fallback Nov 6, 2023
@sreimers sreimers changed the title sip/transp: add win32 tcp/tls local transport addr fallback sip/transp: add win32 local transport addr fallback Nov 6, 2023
@sreimers sreimers merged commit b379bd7 into main Nov 6, 2023
43 checks passed
@sreimers sreimers deleted the win32_einval_tcp_tls_err branch November 6, 2023 15:46
sreimers added a commit that referenced this pull request Nov 6, 2023
tcp_conn_local_get function does not always return information about the host address when the socket has been bound to an unspecified address.

fixes baresip/baresip#2797
@cspiel1
Copy link
Collaborator

cspiel1 commented Nov 9, 2023

@cspiel1 on windows tcp_conn_local_get returns any address if tcp connection is not connected or accepted. So looks like connh is called to early.

So, this PR is only a workaround where a fallback address is assigned?

Should we add some kind of wait condition for the TCP connection?

@sreimers
Copy link
Member Author

sreimers commented Nov 9, 2023

Looks like pjsip does a similiar fallback, so not sure if there is a reliable way (other than waiting for tcp_estab_handler):

        /* Update (again) local address, just in case local address currently
         * set is different now that asynchronous connect() is started.
         */
        addr_len = sizeof(local_addr);
        if (pj_sock_getsockname(sock, &local_addr, &addr_len)==PJ_SUCCESS) {
            pj_sockaddr *tp_addr = &tcp->base.local_addr;

            /* Some systems (like old Win32 perhaps) may not set local address
             * properly before socket is fully connected.
             */
            if (pj_sockaddr_cmp(tp_addr, &local_addr) &&
                pj_sockaddr_has_addr(&local_addr) &&
                pj_sockaddr_get_port(&local_addr) != 0)
            {
                pj_sockaddr_cp(tp_addr, &local_addr);
                sockaddr_to_host_port(tcp->base.pool, &tcp->base.local_name,
                                      &local_addr);
            }
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Broken TCP/TLS sip registration on windows
3 participants